<!---
LICENSE INFORMATION:

Copyright 2007, Hem Talreja

Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License.

You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

VERSION INFORMATION:	(0.001)

 --->
<cfcomponent extends="dbMetaRetreiver">

	<cfset Variables._dbMetaExceptions = "" />

	<cffunction name="init" access="public" returntype="any" >
		<cfargument name="dbMetaExceptions" type="dbMetaExceptions" required="true" />

		<cfset setDBMetaExceptions(Arguments.dbMetaExceptions) />

		<cfreturn this />
	</cffunction>


	<cffunction name="setDBMetaExceptions" access="public" returntype="void" >
		<cfargument name="dbMetaExceptions" type="dbMetaExceptions" required="true" />
		<cfset Variables._dbMetaExceptions = Arguments.dbMetaExceptions />
	</cffunction>
	<cffunction name="getDBMetaExceptions" access="public" returntype="Any">
		<cfreturn Variables._dbMetaExceptions />
	</cffunction>



	<!---
		[columns]
		[meta][counterKey: columnName; UniqueKey: columnList]
		[]
	 --->
	<cffunction name="getTableMeta" returntype="struct" access="public" hint="Returns the meta information about the table">
		<cfargument name="datasource" type="string" required="true" />
		<cfargument name="table" type="string" required="true" />
		<cfargument name="dbname" type="string" required="false" />

		<cfset var Local = StructNew() />

		<!--- will return stcTableInfo --->
		<cfset Local.stcTableInfo = StructNew() />

			<cfset Local.stcTableInfo.Columns = getTableColumns(ArgumentCollection=Arguments) />
			<cfset Local.stcTableInfo.Meta = StructNew() />
			<cfset Local.stcTableInfo.Meta.CounterKey = this.getTableCounterKey(ArgumentCollection=Arguments) />
			<cfset Local.stcTableInfo.Meta.PrimaryKey = this.getTablePrimaryKey(ArgumentCollection=Arguments) />
			<cfset Local.stcTableInfo.Meta.DisplayKey = this.getTableDisplayKey(
															Arguments.table,
															Local.stcTableInfo.Columns,
															Local.stcTableInfo.Meta.CounterKey,
															Local.stcTableInfo.Meta.PrimaryKey) />

		<cfreturn Local.stcTableInfo />
	</cffunction>


	<cffunction name="getTableColumns" returntype="struct" access="public" hint="returns the list of columns as a structure">
		<cfargument name="datasource" type="string" required="true" />
		<cfargument name="table" type="string" required="true" />
		<cfargument name="dbname" type="string" required="false" />

		<cfset var Local = StructNew() />

		<cfset Local.stcColumns = StructNew() />
		<cfset Local.selTableColumns = getColumns(ArgumentCollection=Arguments) />


		<cfloop query="Local.selTableColumns">

			<!--- convert column name to upper case --->
			<cfset Local.strColName = UCASE(Local.selTableColumns.Column_Name) />

			<cfset Local.stcColumns[Local.strColName] = StructNew() />

			<cfset Local.stcColumns[Local.strColName]["COLUMN_NAME"] 			= Local.selTableColumns.column_name />
			<cfset Local.stcColumns[Local.strColName]["DEFAULT_VALUE"] 			= Local.selTableColumns.column_default_value />
			<cfset Local.stcColumns[Local.strColName]["DATA_TYPE"] 				= Local.selTableColumns.type_name />
			<cfset Local.stcColumns[Local.strColName]["COLUMN_SIZE"] 			= Local.selTableColumns.column_size />
			<cfset Local.stcColumns[Local.strColName]["DECIMAL_DIGITS"] 		= Local.selTableColumns.decimal_digits />
			<cfset Local.stcColumns[Local.strColName]["IS_NULLABLE"] 			= YesNoFormat(Trim(Local.selTableColumns.is_nullable)) />
			<cfset Local.stcColumns[Local.strColName]["IS_FK"] 					= YesNoFormat(Trim(Local.selTableColumns.is_foreignKey)) />
			<cfset Local.stcColumns[Local.strColName]["REF_PRIMARYKEY"] 		= Local.selTableColumns.referenced_primaryKey />
			<cfset Local.stcColumns[Local.strColName]["REF_PRIMARYKEY_TABLE"] 	= Local.selTableColumns.referenced_primarykey_Table />



			<cfif Local.selTableColumns.char_octet_length GTE (Local.selTableColumns.column_size * 2)>
				<cfset Local.stcColumns[Local.strColName]["IS_UNICODE"] = "Yes" />
			<cfelse>
				<cfset Local.stcColumns[Local.strColName]["IS_UNICODE"] = "No" />
			</cfif>

			<!--- overwrite the data type for this column, usually done for type:date, datetime, time --->
			<cfset Local.stcColumns[Local.strColName]["DATA_TYPE"] = getDBMetaExceptions().getTableColumnDataType(
															Arguments.table, Local.strColName, Local.selTableColumns.type_name ) />

			<cfset Local.stcColumns[Local.strColName]["COLUMN_LABEL"]= getDBMetaExceptions().getTableColumnLabel(
															Arguments.table, Local.selTableColumns.Column_Name ) />

		</cfloop>

		<cfreturn Local.stcColumns />
	</cffunction>


	<cffunction name="getTablePrimaryKey" returntype="string" access="public" hint="function to return the primary key on the table">
		<cfargument name="datasource" type="string" required="true" />
		<cfargument name="table" type="string" required="true" />
		<cfargument name="dbname" type="string" required="false" />

		<cfset var Local = StructNew() />

		<cfset Local.strPrimaryKey = getDBMetaExceptions().getTablePrimaryKeys(Arguments.Table) />

		<cfif Local.strPrimaryKey IS "">
			<cfset Local.selPrimaryKeys = getColumns( ArgumentCollection=Arguments, filterCriteria=" IS_PRIMARYKEY = 'YES'  " ) />

			<cfif Local.selPrimaryKeys.recordCount>
				<cfset Local.strPrimaryKey = ValueList(Local.selPrimaryKeys.column_name) />
			</cfif>
		</cfif>

		<cfreturn Local.strPrimaryKey />
	</cffunction>


	<cffunction name="getTableCounterKey" returntype="string" access="public" hint="future version may contain counter key recognition... curently please use the exception handler">
		<cfargument name="datasource" type="string" required="true" />
		<cfargument name="table" type="string" required="true" />
		<cfargument name="dbname" type="string" required="false" />

		<cfset var Local = StructNew() />
		<!--- future relase may contain counter key recognition mechanism --->
		<cfset Local.strCounterKey = getDBMetaExceptions().getTableCounterKey(Arguments.Table) />

		<cfif Trim(Local.strCounterKey) IS "">

			<cfset Local.selCounterKeys = getColumns( ArgumentCollection=Arguments, filterCriteria=" UPPER(TYPE_NAME) LIKE '%IDENTITY%' " ) />

			<cfif Local.selCounterKeys.recordCount>
				<cfset Local.strCounterKey = ValueList(Local.selCounterKeys.column_name) />
			</cfif>

		</cfif>

		<cfreturn Local.strCounterKey />
	</cffunction>


	<cffunction name="getTableDisplayKey" returntype="string" access="public">
		<cfargument name="table" type="string" required="true" />
		<cfargument name="columns" type="struct" required="true" />
		<cfargument name="counterKey" type="string" required="true" />
		<cfargument name="primaryKey" type="string" required="false" />

		<cfset var Local = StructNew() />
		<cfset Local.strDisplayKey = getDBMetaExceptions().getTableDisplayKeys(Arguments.Table) />

		<cfif Trim(Local.strDisplayKey) IS "">

			<cfset Local.strPre = ListFirst(Arguments.counterKey,"_") />
			<cfif Local.strPre IS "">
				<cfset Local.strPre = ListFirst(Arguments.primaryKey,"_") />
			</cfif>

			<cfif isDefined("Arguments.columns.#Local.strPre#Name")>
				<cfset Local.strDisplayKey = ListAppend(Local.strDisplayKey,"#Local.strPre#Name") />
 			</cfif>

			<cfif isDefined("Arguments.columns.#Local.strPre#Desc")>
				<cfset Local.strDisplayKey = ListAppend(Local.strDisplayKey,"#Local.strPre#Desc") />
 			</cfif>

		</cfif>

		<cfreturn Local.strDisplayKey />
	</cffunction>


</cfcomponent>